package klass.parse.domain;

import klass.parse.domain.constant.Constant;

import java.util.ArrayList;
import java.util.List;

public class ClassInfo {
    private MajorVersion majorVersion;
    private MinorVersion minorVersion;
    private List<Constant> constantPool;
    private AccessFlag accessFlag;
    private String clazz;
    private String superClass;
    private List<String> interfaces;
    private List<FieldInfo> fields;
    private List<MethodInfo> methods;

    public ClassInfo() {
        constantPool = new ArrayList<Constant>();
        interfaces = new ArrayList<String>();
        fields = new ArrayList<FieldInfo>();
        methods = new ArrayList<MethodInfo>();
    }

    public MajorVersion getMajorVersion() {
        return majorVersion;
    }

    public void setMajorVersion(MajorVersion majorVersion) {
        this.majorVersion = majorVersion;
    }

    public MinorVersion getMinorVersion() {
        return minorVersion;
    }

    public void setMinorVersion(MinorVersion minorVersion) {
        this.minorVersion = minorVersion;
    }

    public List<Constant> getConstantPool() {
        return constantPool;
    }

    public void setConstantPool(List<Constant> constantPool) {
        this.constantPool = constantPool;
    }

    public AccessFlag getAccessFlag() {
        return accessFlag;
    }

    public void setAccessFlag(AccessFlag accessFlag) {
        this.accessFlag = accessFlag;
    }

    public String getClazz() {
        return clazz;
    }

    public void setClazz(String clazz) {
        this.clazz = clazz;
    }

    public String getSuperClass() {
        return superClass;
    }

    public void setSuperClass(String superClass) {
        this.superClass = superClass;
    }

    public List<String> getInterfaces() {
        return interfaces;
    }

    public void setInterfaces(List<String> interfaces) {
        this.interfaces = interfaces;
    }

    public Constant getConstant(short index) {
        return constantPool.get(index);
    }

    public void addConstant(Constant constant) {
        constantPool.add(constant);
    }

    public List<FieldInfo> getFields() {
        return fields;
    }

    public void setFields(List<FieldInfo> fields) {
        this.fields = fields;
    }

    public void addField(FieldInfo fieldInfo) {
        this.fields.add(fieldInfo);
    }

    public void addMethod(MethodInfo methodInfo) {
        this.methods.add(methodInfo);
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();

        builder.append(clazz);
        if (superClass != null) {
            builder.append(" extends ").append(superClass);
        }
        if (interfaces != null && interfaces.size() > 0) {
            builder.append(" implements");
            for (String itfc : interfaces) {
                builder.append(" ").append(itfc);
            }
        }
        builder.append("\n");
        builder.append("MajorVersion: ").append(majorVersion).append("\n");
        builder.append("MinorVersion: ").append(minorVersion).append("\n");
        builder.append("flags:").append(accessFlag).append("\n");
        builder.append("Constant pool:\n");
        for (int i = 1; i < constantPool.size(); ++i) {
            Constant constant = constantPool.get(i);
            String line;
            if (constant.getRawString() != null) {
                line = String.format("#%s = %s\t%s\t//%s", constant.getIndex(), constant.getTypeName(), constant.getRawString(), constant);
            } else {
                line = String.format("#%s = %s\t%s", constant.getIndex(), constant.getTypeName(), constant);
            }
            builder.append(line).append("\n");
        }
        builder.append("\n");

        builder.append("Fields:\n");
        if (fields != null && fields.size() > 0) {
            for (FieldInfo field : fields) {
                builder.append(field.toString()).append("\n");
            }
        }
        builder.append("\n");

        builder.append("Methods:\n");
        if (methods != null && methods.size() > 0) {
            for (MethodInfo method : methods) {
                builder.append(method.toString()).append("\n");
            }
        }
        builder.append("\n");

        return builder.toString();
    }
}
